/**
 * 
 */
package com.study.concurrent;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.study.concurrent.countdownlatch.Boss;
import com.study.concurrent.countdownlatch.Worker;
import com.study.concurrent.cyclicbarrier.CycWorker;

/**
 * @author wali-pp
 *
 */
public class Time {

	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {
		ExecutorService executor = Executors.newCachedThreadPool();
//		timeTest(executor);
//		bossCheckWork(executor);
		cycBossCheckWork();
	}

	private static void cycBossCheckWork() {
		final int parties = 5;
		final CyclicBarrier barrier = new CyclicBarrier(parties, new Runnable() {
			
			@Override
			public void run() {
				System.out.println("all work is finish!!!");
			}
		});
		
		for(int i = 0; i < parties; i++){
			new Thread(new CycWorker(i, barrier)).start();
		}
	}

	private static void bossCheckWork(ExecutorService executor) {
		CountDownLatch latch = new CountDownLatch(3);  
        
        Worker w1 = new Worker(latch,"张三");  
        Worker w2 = new Worker(latch,"李四");  
        Worker w3 = new Worker(latch,"王二");  
          
        Boss boss = new Boss(latch);  
          
        executor.execute(w3);  
        executor.execute(w2);  
        executor.execute(w1);  
        executor.execute(boss);  
          
        executor.shutdown();  
	}

	private static void timeTest(Executor executor) throws InterruptedException {
		long workTime = time(executor, 5, new ActionRunnable());
		System.out.println("workTime = " + workTime);
	}
	
	public static long time(Executor execrutor, int concurrency,
			final Runnable action) throws InterruptedException{
		final CountDownLatch ready = new CountDownLatch(concurrency);
		final CountDownLatch start = new CountDownLatch(1);
		final CountDownLatch done = new CountDownLatch(concurrency);
		for(int i = 0; i < concurrency; i++){
			execrutor.execute(new Runnable() {
				
				@Override
				public void run() {
					ready.countDown(); // Tell timer we're ready
					try {
						start.await(); // Wait till peers are ready
						action.run();
					} catch (InterruptedException e) {
						Thread.currentThread().interrupt();
					} finally {
						done.countDown(); // Tell timer we're done
					}
				}
			});
		}
		
		ready.await(); // Wait for all workers to be ready
		long startNanos = System.nanoTime();
		start.countDown(); // And they're off!
		done.await(); // Wait for all workers to finish
		return System.nanoTime() - startNanos;
	}
	
	static class ActionRunnable implements Runnable{

		@Override
		public void run() {
			System.out.println("name = " + Thread.currentThread().getName());
		}
		
	}

}
